package online.chazi.netkit;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import online.chazi.netkit.channel.NetkitPipelineFactory;
import online.chazi.netkit.channel.NetkitWebSocketPipelineFactory;
import online.chazi.netkit.listener.DefaultStartUpListener;
import online.chazi.netkit.listener.StartUpListener;

/**
 * 说明：作者很懒，什么都没留下
 * Created by 叉子同学 on 2020-04-24 13:36
 */
@Slf4j
@Data
public class NetkitServer {

    private boolean startup = false;
    private final NetkitContext context;
    private String bindHost = "0.0.0.0";
    private int port = 8000;
    private int maxConnections = 30000;
    private int maxMessagePacketSize = 1048576;

    private StartUpListener startUpListener = new DefaultStartUpListener();
    private ServerBootstrap bootstrap;
    private ChannelFuture bootstrapChannelFuture;

    public NetkitServer(NetkitContext context) {
        this.context = context;
    }

    public NetkitServer(NetkitContext context, int port) {
        this.context = context;
        this.port = port;
    }

    public NetkitServer(NetkitContext context, String bindHost, int port) {
        this.context = context;
        this.port = port;
        this.bindHost = bindHost;
    }

    public void setMaxConnections(int maxConnections) {
        this.maxConnections = maxConnections;
    }

    public void startup() {
        startup(new NetkitPipelineFactory(context));
    }

    public void startupWebSocket(String path) {
        startup(new NetkitWebSocketPipelineFactory(context, path));
    }

    public void startup(ChannelInitializer<?> handler) {

        if (startup) throw new IllegalArgumentException("已经启动了！不要重复启动！");
        startup = true;

        context.setMaxConnections(this.maxConnections);

        try {
            bootstrap = new ServerBootstrap()
                    .group(context.getBossGroup(), context.getWorkGroup())
                    .channel(NioServerSocketChannel.class)
                    .childOption(ChannelOption.SO_KEEPALIVE, true)
                    .childHandler(handler);

            bootstrapChannelFuture = bootstrap.bind(port).addListener(future -> {
                startUpListener.startup(future.isSuccess());
            }).sync();
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            shutdown();
        }

    }

    public void shutdown() {
        this.context.release();
        //this.heartbeatService.shutdown();
        bootstrapChannelFuture.channel().close();
        context.getBossGroup().shutdownGracefully();
        context.getWorkGroup().shutdownGracefully();
    }

}
